package com.demo.aop.overview;

import com.demo.aop.overview.interceptor.AfterInterceptor;
import com.demo.aop.overview.interceptor.BeforeInterceptor;
import com.demo.aop.overview.service.DefaultImService;
import com.demo.aop.overview.service.ImService;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

public class InterceptorDemo {

    public static void main(String[] args) {


        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        DefaultImService defaultImService = new DefaultImService();

        Object proxy = Proxy.newProxyInstance(cl, new Class[]{ImService.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (!ImService.class.isAssignableFrom(method.getDeclaringClass())) {
                    return null;
                }
                Map<String, Long> map = new HashMap<>(2);
                try {
                    //前置通知
                    BeforeInterceptor beforeInterceptor = new BeforeInterceptor() {
                        @Override
                        public Object before(Object proxy, Method method, Object[] args) {
                            return System.nanoTime();
                        }
                    };
                    long start = (long) beforeInterceptor.before(proxy, method, args);
                    map.put("start", start);
                    Object result = method.invoke(defaultImService, args);

                    AfterInterceptor afterInterceptor = new AfterInterceptor() {
                        @Override
                        public Object after(Object proxy, Method method, Object[] args) {
                            return System.nanoTime();
                        }
                    };
                    long after = (long) afterInterceptor.after(proxy, method, args);
                    map.put("after", after);
                    return result;
                }finally {
                    Long start = map.get("start");
                    Long after = map.get("after");
                    System.out.println("方法执行耗时：" + (after - start));
                }
            }
        });


        ImService service = (ImService) proxy;
        service.send(" -> hello world!");
    }
}
